/*
 *	ncp_hr_collector_app.c
 *
 *	Created on: 2018年4月4日
 *	Author: NKJ
 */

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

/* BG stack headers */
#include "bg_types.h"
#include "gecko_bglib.h"

/* Own header */
#include "ncp_hr_collector_app.h"
#include "gecko_interface.h"

#define FLASH_PS_KEY_HRM_MAC (FLASH_PS_KEY_OTA_DEVICE_NAME+1)

BleCB blecb = {
    .local_mac.addr = {0},
    .txpower = 0,
    .pin = 1234,
#ifdef EFR_IM_SOC
    .appsta = STOP,
    .advsta = STOP,
    .scansta = STOP,
    .workstyle = CLIENT,
    .atcmdbuff = {0},
    .usart0dmachannel = 0,
    .usart0dmarxfifo = {0},
#endif
    .scanfilter = {0},
    .scanfilterlen = 0,
    .connindex = 0,
    .connections = 0,

    .conncb[0].mac.addr = {0},
    .conncb[0].connectedid = 0xFF,
    .conncb[0].mainservice = 1,
    .conncb[0].discoverserviceindex = 0,
    .conncb[0].service_uuid = {(uint8_t *)"\x00\x18",(uint8_t *)"\x0D\x18",(uint8_t *)"\x0F\x18"},
    .conncb[0].service_uuid_bit = {16,16,16}, 
    .conncb[0].charact_uuid = {{(uint8_t *)"\x00\x2A",0},{(uint8_t *)"\x37\x2A",0},{(uint8_t *)"\x19\x2A",0}},
    .conncb[0].charact_uuid_bit = {{16,0},{16,0},{16,0}}, 
    .conncb[0].service_handle = {0},
    .conncb[0].charact_handle = {0},
    .conncb[0].charact_properties = {0},
    .conncb[0].discoverstate = SCANNING,
    .conncb[0].bondsta = DISABLE,
    .conncb[0].pin = 1234,
    .conncb[0].discontime = 0,
#if (MAX_CONNECTIONS > 1)
    .conncb[1] = CONNCB_DEFAULT,
#endif
};

void resp_evt_scan_response(struct gecko_cmd_packet* evt);

void appHandleEvents(struct gecko_cmd_packet *evt)
{
	if (NULL == evt) 
	{
		return;
	}

	/* Handle events */
    BGLIB_DBG("BGLIB_MSG_ID: %#X\r\n",BGLIB_MSG_ID(evt->header));
	switch (BGLIB_MSG_ID(evt->header)) 
	{
		case gecko_evt_system_boot_id:
        {
			gecko_printf("System booted. Starting scaning. \n");

            memcpy(blecb.local_mac.addr,gecko_cmd_system_get_bt_address()->address.addr,6);

            gecko_printf("LOC MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",  blecb.local_mac.addr[5],blecb.local_mac.addr[4],blecb.local_mac.addr[3],
                                                                    blecb.local_mac.addr[2],blecb.local_mac.addr[1],blecb.local_mac.addr[0]);

            struct gecko_msg_flash_ps_load_rsp_t* re = gecko_cmd_flash_ps_load(FLASH_PS_KEY_HRM_MAC);
            memcpy(blecb.conncb[blecb.connindex].mac.addr,re->value.data,6);
            gecko_printf("HRM MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",  blecb.conncb[blecb.connindex].mac.addr[5],blecb.conncb[blecb.connindex].mac.addr[4],
                                                                        blecb.conncb[blecb.connindex].mac.addr[3],blecb.conncb[blecb.connindex].mac.addr[2],
                                                                        blecb.conncb[blecb.connindex].mac.addr[1],blecb.conncb[blecb.connindex].mac.addr[0]);

			/* Set advertising parameters. 100ms advertisement interval. All channels used.
			* The first two parameters are minimum and maximum advertising interval, both in
			* units of (milliseconds * 1.6). The third parameter '7' sets advertising on all channels. */
			//gecko_cmd_le_gap_set_adv_parameters(160, 160, 7);
			/* Start general advertising and enable connections. */
			//gecko_cmd_le_gap_set_mode(le_gap_general_discoverable, le_gap_undirected_connectable);

            //gecko_cmd_le_gap_set_scan_parameters(0xC8,0xC8,1);
            gecko_cmd_le_gap_discover(le_gap_discover_observation);
        }
        break;

        case gecko_evt_le_gap_scan_response_id:

            resp_evt_scan_response(evt);

            //gecko_printf("Scan...\r\n");
            //gecko_printf("Rssi: %02X\r\n",evt->data.evt_le_gap_scan_response.rssi & 0xff);
            //gecko_printf("Packet type: %02X\r\n",evt->data.evt_le_gap_scan_response.packet_type);
            //uint8_t *p = evt->data.evt_le_gap_scan_response.address.addr;
            //gecko_printf("Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n",p[5],p[4],p[3],p[2],p[1],p[0]);
            //gecko_printf("Address type: %02X\r\n",evt->data.evt_le_gap_scan_response.address_type);
            //gecko_printf("Bonding: %02X\r\n",evt->data.evt_le_gap_scan_response.bonding);
            //gecko_printf("Data: ");
            //for(uint8_t i = 0;i < evt->data.evt_le_gap_scan_response.data.len;i ++)
            //{
            //    gecko_printf("%02X ",evt->data.evt_le_gap_scan_response.data.data[i]);
            //}
            //gecko_printf("\r\n\r\n");
        break;

        case gecko_evt_le_connection_bt5_opened_id:
        case gecko_evt_le_connection_opened_id:
            blecb.connections ++;
            if(blecb.connections > MAX_CONNECTIONS)
            {
                blecb.connections = MAX_CONNECTIONS;
                gecko_cmd_le_gap_end_procedure();
                gecko_printf("%02X:SCAN STOP\r\n",RETURN_MSG_ATCMD_SCANSTOP);
                break;
            }

            if(evt->data.evt_le_connection_opened.master)
            {
                if(blecb.connindex >= MAX_CONNECTIONS)   break;

                blecb.conncb[blecb.connindex].connectedid = evt->data.evt_le_connection_opened.connection;

                //如果地址与保存地址不一样则更新保存地址
                if(memcmp(blecb.conncb[blecb.connindex].mac.addr,evt->data.evt_le_connection_opened.address.addr,6))
                {
                    //存储新的心率表物理地址
                    gecko_cmd_flash_ps_erase(FLASH_PS_KEY_HRM_MAC);
                    gecko_cmd_flash_ps_save(FLASH_PS_KEY_HRM_MAC,6,evt->data.evt_le_connection_opened.address.addr);
                    memcpy(blecb.conncb[blecb.connindex].mac.addr,evt->data.evt_le_connection_opened.address.addr,6);
                    gecko_printf("HRM MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",  blecb.conncb[blecb.connindex].mac.addr[5],blecb.conncb[blecb.connindex].mac.addr[4],
                                                                                blecb.conncb[blecb.connindex].mac.addr[3],blecb.conncb[blecb.connindex].mac.addr[2],
                                                                                blecb.conncb[blecb.connindex].mac.addr[1],blecb.conncb[blecb.connindex].mac.addr[0]);
                }
            }
            gecko_printf("%02X:OPENED MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n",RETURN_MSG_OPENED4,
                                                                                blecb.conncb[blecb.connindex].mac.addr[5],blecb.conncb[blecb.connindex].mac.addr[4],
                                                                                blecb.conncb[blecb.connindex].mac.addr[3],blecb.conncb[blecb.connindex].mac.addr[2],
                                                                                blecb.conncb[blecb.connindex].mac.addr[1],blecb.conncb[blecb.connindex].mac.addr[0]);
        break;

        case gecko_evt_le_connection_closed_id:
            blecb.connections --;
            //blecb.connindex = findConnectHandleIndex(blecb,evt->data.evt_le_connection_closed.connection);
            if(blecb.connindex == 0xff)
            {
                //gecko_cmd_system_reset(0);
                break;
            }

            blecb.conncb[blecb.connindex].connectedid = 0xFF;
            //memset(blecb.conncb[blecb.connindex].mac.addr,0,6);
            blecb.conncb[blecb.connindex].discoverserviceindex = 0;
            blecb.conncb[blecb.connindex].discoverstate = SCANNING;
            memset((uint8_t *)blecb.conncb[blecb.connindex].service_handle,0,sizeof(blecb.conncb[blecb.connindex].service_handle));
            memset((uint8_t *)blecb.conncb[blecb.connindex].charact_handle,0,sizeof(blecb.conncb[blecb.connindex].charact_handle));
            blecb.conncb[blecb.connindex].bondsta = DISABLE;
            blecb.conncb[blecb.connindex].discontime = 0;

            gecko_printf("%02X:CLOSED\r\n",RETURN_MSG_CLOSED);
            gecko_cmd_le_gap_discover(le_gap_discover_observation);               
            gecko_printf("%02X:SCAN START\r\n",RETURN_MSG_ATCMD_SCANSTART);
            
        break;

        case gecko_evt_hardware_soft_timer_id:
            switch (evt->data.evt_hardware_soft_timer.handle) 
            {
                case 7:
                    gecko_printf("LED timer\r\n");
                break;
                default:
                break;
            }
        break;

		default:
        break;
  }
}

void resp_evt_scan_response(struct gecko_cmd_packet* evt)
{
    static uint8_t scan_counts = 0;
    static int8_t rssi = -127;
    static bd_addr mac;

    uint8_t index = 0;
    if(blecb.connindex >= MAX_CONNECTIONS)
    {
        gecko_printf("A0:SCAN STOP\r\n");
        gecko_cmd_le_gap_end_procedure();
        return;
    }
    while(index < evt->data.evt_le_gap_scan_response.data.len)
    {
        uint8_t field_length = evt->data.evt_le_gap_scan_response.data.data[index];
        uint8_t field_type = evt->data.evt_le_gap_scan_response.data.data[index + 1];
        if((field_type >= BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE) && (field_type <= BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE))
        {
            for(uint8_t i = 0;i < (field_length - 1);)
            {
                if(!memcmp(&evt->data.evt_le_gap_scan_response.data.data[index + 2],
                (uint8_t *)blecb.conncb[blecb.connindex].service_uuid[blecb.conncb[blecb.connindex].mainservice],
                blecb.conncb[blecb.connindex].service_uuid_bit[blecb.conncb[blecb.connindex].mainservice] / 8))
                {
                    uint8_t *p = evt->data.evt_le_gap_scan_response.address.addr;
                    gecko_printf("FF:SCAN...%d [%02X:%02X:%02X:%02X:%02X:%02X]\r\n",scan_counts,p[5],p[4],p[3],p[2],p[1],p[0]);

                    //扫描次数不够或物理地址与存储的物理地址不一致
                    if(memcmp(blecb.conncb[blecb.connindex].mac.addr,evt->data.evt_le_gap_scan_response.address.addr,6))
                    {
                        if(scan_counts < 128)
                        {
                            if(evt->data.evt_le_gap_scan_response.rssi > rssi)
                            {
                                memcpy(mac.addr,evt->data.evt_le_gap_scan_response.address.addr,6);
                                rssi = evt->data.evt_le_gap_scan_response.rssi;
                            }
                            scan_counts ++;
                            return;
                        }
                        if(memcmp(mac.addr,evt->data.evt_le_gap_scan_response.address.addr,6))
                            return;
                    }

                    gecko_cmd_le_gap_end_procedure();
                    gecko_cmd_le_gap_set_conn_parameters(200,200,0,100);
                    if(gecko_cmd_le_gap_open(evt->data.evt_le_gap_scan_response.address,evt->data.evt_le_gap_scan_response.address_type)->result)
                    {
                        gecko_cmd_le_gap_discover(le_gap_discover_observation);               
                    }

                    scan_counts = 0;
                    rssi = -127;
                    return;
                }
                i += blecb.conncb[blecb.connindex].service_uuid_bit[blecb.conncb[blecb.connindex].mainservice] / 8;
            }
        }
        index = index + field_length + 1;
    }

    static uint8_t rotate = 0;
    const char *symbol[7] = {">    ",">>   ",">>>  "," >>> ","  >>>","   >>","    >"};
    gecko_printf("FF:SCAN ... WAIT TARGET ... [%s] \r",symbol[rotate]);
    fflush(stdout);
    rotate ++;
    rotate %= 7;
}

